﻿package com.hxh.ocean.controller{

	import com.fileitup.fisixengine.collisions.DetectionModes;
	import com.fileitup.fisixengine.collisions.ReactionModes;
	import com.fileitup.fisixengine.core.*;
	import com.fileitup.fisixengine.particles.CircleParticle;
	import com.fileitup.fisixengine.primitives.Surface;
	import com.hxh.components.CustomColorPicker;
	import com.hxh.ocean.events.*;
	import com.hxh.ocean.helpers.*;
	import com.hxh.ocean.view.*;
	import com.hxh.utils.*;
	
	import flash.display.MovieClip;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.ColorTransform;
	import flash.net.*;
	
	import mx.controls.Alert;
	import mx.managers.CursorManager;
	

	public class OceanManager extends SuperManager {
	
		private var _background:Sprite;
		private var _bgColor:uint;
		private var _mainMenu:Array;
		private var _configButtons:Array;
		private var _musicManager:MusicManager;
		private var _databaseManager:DatabaseManager;
		
		private var _bgColorPicker:CustomColorPicker;
		private var _bubbleColorPicker:CustomColorPicker;
		private var _busyIcon:BusyIcon;

		// Initialization:
		public function OceanManager() {
			//Pause = true;
			
			//Add some random bubbles for a good testing population
			/*for (var i:int = 0; i < 10; i++){
			var test:Bubble = new Bubble("Test"+i, new BubbleView());
			test.Scale = Maths.randomInt(2,4)/10;
			test.Speed = Maths.randomInt(14,20);
			test.x = 400;
			test.y = 300;
			//test.x = Maths.randomInt(0, Helper.SCREEN_WIDTH);
			//test.y = Maths.randomInt(0, Helper.SCREEN_HEIGHT);
			addChild(test);
			}*/
			_busyIcon = new BusyIcon();
			addChild(_busyIcon);
			_busyIcon.x = 400 - (_busyIcon.width/2);
			_busyIcon.y = 300 - (_busyIcon.height/2);
			_busyIcon.setLabel("Retrieving data...");
			_databaseManager = new DatabaseManager();
			_databaseManager.addEventListener(Events.STAGE_INFO_LOADED, initStage);
			_databaseManager.addEventListener(Events.CHANGES_SAVED, changesSaved);
			
			//Physics engine
			_fisixEngine.setRender(true);
			_fisixEngine.setRenderGraphics(graphics);
			_fisixEngine.setAllDetectionModes(DetectionModes.HYBRID_RAYCAST);
			_fisixEngine.setAllReactionModes(ReactionModes.PHYSICAL);
			_fisixEngine.setGravity(0,0);
			
		}
		
		/********************* GAME LOOP ***************************/
		
		override protected function doUpdate():void{
			_fisixEngine.mainLoop();
		}

		/********************* PUBLIC METHODS **********************/

		//Set the color of the background
		public function setBGColor(color:uint):void {
			var colorTransform:ColorTransform = new ColorTransform();
			colorTransform.color=color;
			_background.transform.colorTransform=colorTransform;
			_bgColor = color;
		}
		
		//Set the stage gravity
		public function setGravity(value:Number):void{
			_fisixEngine.setGravity(0, value);
		}

		/********************* PRIVATE METHODS *********************/
		
		private function initStage(evt:Event):void{
			//Remove busy icon
			removeChild(_busyIcon);
			_busyIcon = null;
			//Bubble effect
			EffectRenderer.addEmitter(EffectFactory.effect_OceanBubble());
			//Build background
			_background = new Background();
			addChild(_background);
			_background.x=400;
			_background.y=300;
			
			_bgColor = _databaseManager.StageInfo.BackgroundColor;
			setBGColor(_bgColor);
			
			buildMainMenu();
			
			buildConfigButton();
			
			buildBorder();
			
			toggleSound(_databaseManager.StageInfo.PlaySFX);
			toggleLabel(_databaseManager.StageInfo.ShowLabel);
			_musicManager = new MusicManager(_databaseManager.StageInfo.PlayMusic);
		}
		
		private function buildBorder():void{
			
			//Bottom
			var surface:Surface = new Surface(new com.fileitup.fisixengine.core.Vector(0,Helper.SCREEN_HEIGHT),
											  new com.fileitup.fisixengine.core.Vector(Helper.SCREEN_WIDTH,Helper.SCREEN_HEIGHT),4);
			_fisixEngine.addObject(surface);
			surface.color = 0x000000;
			surface.bounce = 0.5;
			
			//Top
			surface = new Surface(new com.fileitup.fisixengine.core.Vector(0,0),
											  new com.fileitup.fisixengine.core.Vector(Helper.SCREEN_WIDTH,0),4);
			_fisixEngine.addObject(surface);
			surface.color = 0x000000;
			surface.bounce = 0.5;
			
			//Left
			surface = new Surface(new com.fileitup.fisixengine.core.Vector(0,0),
											  new com.fileitup.fisixengine.core.Vector(0,Helper.SCREEN_HEIGHT),4);
			_fisixEngine.addObject(surface);
			surface.color = 0x000000;
			surface.bounce = 0.5;
			
			//Right
			surface = new Surface(new com.fileitup.fisixengine.core.Vector(Helper.SCREEN_WIDTH,0),
											  new com.fileitup.fisixengine.core.Vector(Helper.SCREEN_WIDTH,Helper.SCREEN_HEIGHT),4);
			_fisixEngine.addObject(surface);
			surface.color = 0x000000;
			surface.bounce = 0.5;
		}

		private function buildConfigButton():void {

			_configButtons = new Array();
			
			var view:MovieClip = new ButtonView();
			view.setBaseSprite(new ConfigGear());
			var btnChangeBG:BubbleButton=new BubbleButton("Change BG Color",view);
			btnChangeBG.Scale=0.5;
			btnChangeBG.x=20;
			btnChangeBG.y=580;
			btnChangeBG.addEventListener(Events.BUBBLE_CLICK, changeBGColor);
			newConfigButton(btnChangeBG);

			view = new ButtonView();
			view.setBaseSprite(new SimpleNote());
			var label:String;
			if (_databaseManager.StageInfo.PlayMusic){
				label = "Turn Music Off";
			}
			else{
				label = "Turn Music On";
			}
			var btnMusic:BubbleButton=new BubbleButton(label ,view);
			btnMusic.Scale=0.5;
			btnMusic.x=60;
			btnMusic.y=580;
			btnMusic.addEventListener(Events.BUBBLE_CLICK, buttonMusicClick);
			btnMusic.Highlighted = _databaseManager.StageInfo.PlayMusic;
			newConfigButton(btnMusic);

			view = new ButtonView();
			view.setBaseSprite(new SimpleSpeaker());
			if (_databaseManager.StageInfo.PlaySFX){
				label = "Turn Sound Off";
			}
			else{
				label = "Turn Sound On";
			}
			var btnSound:BubbleButton=new BubbleButton(label, view);
			btnSound.Scale=0.5;
			btnSound.x=100;
			btnSound.y=580;
			btnSound.addEventListener(Events.BUBBLE_CLICK, buttonSoundClick);
			btnSound.Highlighted = _databaseManager.StageInfo.PlaySFX;
			newConfigButton(btnSound);
			
			view = new ButtonView();
			view.setBaseSprite(new ABCText());
			if (_databaseManager.StageInfo.ShowLabel){
				label = "Turn Label Off";
			}
			else{
				label = "Turn Label On";
			}
			var btnLabel:BubbleButton=new BubbleButton(label, view);
			btnLabel.Scale=0.5;
			btnLabel.x=140;
			btnLabel.y=580;
			btnLabel.addEventListener(Events.BUBBLE_CLICK, buttonLabelClick);
			btnLabel.Highlighted = _databaseManager.StageInfo.ShowLabel;
			newConfigButton(btnLabel);
		}
		
		private function changeBGColor(evt:Event):void{
			if (_bgColorPicker!=null&&contains(_bgColorPicker)){
				removeChild(_bgColorPicker);
			}
			_bgColorPicker = new CustomColorPicker(_bgColor);
			_bgColorPicker.addEventListener(CustomColorPicker.CONFIRM_COLOR, confirmChangeBGColor);
			_bgColorPicker.x = BubbleButton(evt.target).x-20;
			_bgColorPicker.y = BubbleButton(evt.target).y-80;
			addChild(_bgColorPicker);
		}
		
		private function confirmChangeBGColor(evt:Event):void{
			showSavingIcon();
			_databaseManager.setBGColor(_bgColorPicker.PickedColor);
			setBGColor(_bgColorPicker.PickedColor);
			_bgColorPicker.destroy();
		}

		private function buttonSoundClick(evt:Event):void {
			var button:BubbleButton = BubbleButton(evt.target);
			button.Highlighted = !button.Highlighted;
			
			if (button.Highlighted){
				button.Label = "Turn Sound Off";
			}
			else{
				button.Label = "Turn Sound On";
			}
			
			toggleSound(button.Highlighted);
		}
		
		private function toggleSound(sound:Boolean):void{
			showSavingIcon();
			for (var i:int = 0; i < _mainMenu.length; i++) {
				_mainMenu[i].PlaySFX = sound;
				var children:Array = _mainMenu[i].getChildren();
				for (var j:int = 0; j < children.length; j++){
					children[j].PlaySFX = sound;
				}
			}
			
			for (i = 0; i < _configButtons.length; i++){
				_configButtons[i].PlaySFX = sound;
			}	
			
			_databaseManager.setStageSound(sound);
		}

		private function buttonMusicClick(evt:Event):void {
			showSavingIcon();
			var button:BubbleButton = BubbleButton(evt.target);
			button.Highlighted = !button.Highlighted;
			
			if (button.Highlighted){
				button.Label = "Turn Music Off";
			}
			else{
				button.Label = "Turn Music On";
			}
			
			_musicManager.toggleMusic(button.Highlighted);
			_databaseManager.setStageMusic(button.Highlighted);
		}
		
		private function buttonLabelClick(evt:Event):void {
			var button:BubbleButton = BubbleButton(evt.target);
			button.Highlighted = !button.Highlighted;
			
			if (button.Highlighted){
				button.Label = "Turn Label Off";
			}
			else{
				button.Label = "Turn Label On";
			}
			
			toggleLabel(button.Highlighted);
		}
		
		private function toggleLabel(label:Boolean):void{
			showSavingIcon();
			for (var i:int = 0; i < _mainMenu.length; i++) {
				Bubble(_mainMenu[i]).ShowLabel = label;
			}
			_databaseManager.setStageLabel(label);
		}

		private function buildMainMenu():void {
			//Main menu array
			_mainMenu = new Array();
			//Portfolio Item
			var item:MenuItem=new MenuItem("My Portfolio");
			item.BaseColor=0xA23CE6;
			item.Scale=0.8;
			item.x=Maths.randomInt(30, Helper.SCREEN_WIDTH-30);
			item.y=Maths.randomInt(30, Helper.SCREEN_HEIGHT-30);
			//Portfolio children
			var childItem:MenuChildItem=new MenuChildItem("Java","http://blogs.hxhieu.net/?cat=4");
			buildChildItemListeners(childItem);

			item.newChildItem(childItem);
			childItem=new MenuChildItem("ASP.NET","http://blogs.hxhieu.net/?cat=5");
			buildChildItemListeners(childItem);

			item.newChildItem(childItem);
			childItem=new MenuChildItem("C#","http://blogs.hxhieu.net/?cat=5");
			buildChildItemListeners(childItem);

			item.newChildItem(childItem);
			childItem=new MenuChildItem("Adobe Flash","http://blogs.hxhieu.net/?cat=6");
			buildChildItemListeners(childItem);

			item.newChildItem(childItem);
			buildMenuItemListeners(item);
			newMenuItem(item);

			//About Item
			item=new MenuItem("About Me", "Under Construction");
			item.BaseColor=0xFF0000;
			item.Scale=0.7;
			item.x=Maths.randomInt(30, Helper.SCREEN_WIDTH-30);
			item.y=Maths.randomInt(30, Helper.SCREEN_HEIGHT-30);
			buildMenuItemListeners(item);
			newMenuItem(item);

			//Contact Item
			item=new MenuItem("Contact Me", "Under Construction");
			item.BaseColor=0x00FF00;
			item.Scale=0.6;
			item.x=Maths.randomInt(30, Helper.SCREEN_WIDTH-30);
			item.y=Maths.randomInt(30, Helper.SCREEN_HEIGHT-30);
			buildMenuItemListeners(item);
			newMenuItem(item);

			//Forums Item
			item=new MenuItem("My Forums", "Under Construction");
			item.BaseColor=0x00FF;
			item.Scale=0.8;
			item.x=Maths.randomInt(30, Helper.SCREEN_WIDTH-30);
			item.y=Maths.randomInt(30, Helper.SCREEN_HEIGHT-30);
			buildMenuItemListeners(item);
			newMenuItem(item);

			//Blogs Item
			item=new MenuItem("My Blogs","http://blogs.hxhieu.net");
			item.BaseColor=0xFFFF00;
			item.Scale=0.8;
			item.x=Maths.randomInt(30, Helper.SCREEN_WIDTH-30);
			item.y=Maths.randomInt(30, Helper.SCREEN_HEIGHT-30);
			buildMenuItemListeners(item);
			newMenuItem(item);
			
			//Links Item
			item=new MenuItem("Links");
			item.x=Maths.randomInt(30, Helper.SCREEN_WIDTH-30);
			item.y=Maths.randomInt(30, Helper.SCREEN_HEIGHT-30);
			item.Scale=0.9;
			item.BaseColor=0x50A0FF;

			childItem=new MenuChildItem("My Facebook","http://www.facebook.com/people/Hugh-Hoang/1315144774");
			buildChildItemListeners(childItem);
			item.newChildItem(childItem);
			
			childItem=new MenuChildItem("flintparticles.org","http://flintparticles.org/");
			buildChildItemListeners(childItem);
			item.newChildItem(childItem);
			
			childItem=new MenuChildItem("Auckland University of Technology","http://www.aut.ac.nz");
			buildChildItemListeners(childItem);
			item.newChildItem(childItem);
			
			childItem=new MenuChildItem("Adobe FLEX","http://www.adobe.com/products/flex/");
			buildChildItemListeners(childItem);
			item.newChildItem(childItem);
			
			childItem=new MenuChildItem("Adobe.com","http://www.adobe.com/");
			buildChildItemListeners(childItem);
			item.newChildItem(childItem);
			
			buildMenuItemListeners(item);
			newMenuItem(item);

			//10 children
			item=new MenuItem("10 children");
			item.x=Maths.randomInt(30, Helper.SCREEN_WIDTH-30);
			item.y=Maths.randomInt(30, Helper.SCREEN_HEIGHT-30);

			for (var i:int = 1; i <= 10; i++) {
				childItem=new MenuChildItem("Child "+i);
				buildChildItemListeners(childItem);
				item.newChildItem(childItem);
			}
			buildMenuItemListeners(item);
			newMenuItem(item);
		}

		private function buildMenuItemListeners(item:MenuItem):void {
			item.addEventListener(Events.BUBBLE_CLICK, menuItemClick);
			item.addEventListener(Events.POPOUT_FINISH, menuItemPopOutFinish);
			item.addEventListener(Events.SHOWCHILDREN_FINISH, menuItemShowChildrenFinish);
		}

		private function buildChildItemListeners(childItem:MenuChildItem):void {
			childItem.addEventListener(Events.BUBBLE_CLICK, childItemClick);
			childItem.addEventListener(Events.POPOUT_FINISH, childItemPopOutFinish);
		}

		private function newMenuItem(item:MenuItem):void {
			//Add to the list
			_mainMenu.push(item);
			//Add to the stage
			addChildObject(item);
			//Implement physic
			var ob:CircleParticle = new CircleParticle(item.x, item.y, item.Radius);
			_fisixEngine.addObject(ob);
			item.FisixContainer = ob;
			ob.color = 0x000000;
			ob.mass = 10*item.Radius;
			ob.bounce = 0.03*item.Radius;
			ob.thrust(Maths.randomInt(-5,5), Maths.randomInt(-5,5));
			_fisixEngine.newParticleAttacher(item, ob);
		}
		
		private function newConfigButton(button:BubbleButton):void{
			//Add to the list
			_configButtons.push(button);
			//Add the the stage
			addChild(button);
			//Implement physics
			var ob:CircleParticle = new CircleParticle(button.x, button.y, button.Radius);
			_fisixEngine.addObject(ob);
			ob.fixed = true;
			ob.color = 0x000000;
			ob.mass = 100*button.Radius;
			_fisixEngine.newParticleAttacher(button, ob);
		}

		private function menuItemClick(evt:Event):void {
			var item:MenuItem=MenuItem(evt.target);
			item.popOut();
			item.Speed=0;
			if (item.TargetURL!=null) {
				if (item.TargetURL == "Under Construction"){
					Alert.show("The page you request is under construction.\nPlease come back later.\n", "Sorry...");
				}
				else{
					navigateToURL(new URLRequest(item.TargetURL));
				}
			}
		}

		private function menuItemPopOutFinish(evt:Event):void {
			var item:MenuItem=MenuItem(evt.target);
			//removeChild(item);
			item.startShowChildrenTimer();
			showChildren(item);
		}

		private function showChildren(item:MenuItem):void {
			var children:Array=item.getChildren();
			for (var i:int = 0; i < children.length; i++) {
				addChild(children[i]);
			}
			item.placingChildren();
		}

		private function menuItemShowChildrenFinish(evt:Event):void {
			var item:MenuItem=MenuItem(evt.target);
			if (item.getChildren().length>0) {
				hideChildren(item);
			} else {
				addChild(item);
				item.popIn();
			}
		}

		private function hideChildren(item:MenuItem):void {
			var children:Array=item.getChildren();
			for (var i:int = 0; i < children.length; i++) {
				children[i].popOut();
			}
		}

		private function childItemClick(evt:Event):void {
			var item:MenuChildItem=MenuChildItem(evt.target);
			if (item.TargetURL!=null) {
				navigateToURL(new URLRequest(item.TargetURL));
			}
		}


		private function childItemPopOutFinish(evt:Event):void {
			var childItem:MenuChildItem=MenuChildItem(evt.target);
			var item:MenuItem=childItem.ParentItem;
			childItem.IsAlive=false;
			if (item.noActiveChild()) {
				addChild(item);
				item.popIn();
			}
		}
		
		private function showSavingIcon():void{
			CursorManager.setBusyCursor();
			if (_busyIcon != null && contains(_busyIcon))
			{
				removeChild(_busyIcon);
			}
			_busyIcon = new BusyIcon();
			addChild(_busyIcon);
			_busyIcon.scaleX = 0.6;
			_busyIcon.scaleY = 0.6;
			_busyIcon.x = 720;
			_busyIcon.y = 600;
			_busyIcon.setLabel("Saving...");
		}
		
		private function changesSaved(evt:Event):void{
			CursorManager.removeBusyCursor();
			if (_busyIcon != null && contains(_busyIcon))
			{
				removeChild(_busyIcon);
				_busyIcon = null;
			}
		}
	}

}